//
//  T3FTNRouteManager.swift
//  t3_map
//
//  Created by Cunhai Li on 2024/12/11.
//

import Foundation
import QMapKit
import Flutter
import MapKit

class T3FTNRouteManager: NSObject {

    private lazy var search = QMSSearcher(delegate: self)
    private var strongSelf: T3FTNRouteManager?
    private var result: FlutterResult?

    /// 步行算路
    func walkRoute(arguments: Any?, result: @escaping FlutterResult) {
        self.result = result

        /// arguments示例：
        /// ```
        /// {
        ///     "origin": {
        ///         "longitude": 11.111
        ///         "latitude": 11.111
        ///    },
        ///    "destination": {
        ///         "longitude": 11.111
        ///         "latitude": 11.111
        ///    },
        /// }
        /// ```
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            if let origin = jsonToCoordinate2D(key: "origin", json: json),
                let destination = jsonToCoordinate2D(key: "destination", json: json) {

                //构建request
                let request = QMSWalkingRouteSearchOption()
                request.setFrom(origin)
                request.setTo(destination)
                /// 保持引用
                strongSelf = self
                search.searchWithWalkingRouteSearchOption(request)
            }
            else {
                let response = ["error": T3FTNRouteManagerError.dataParseFail.localizedDescription]
                let value = try? T3FJsonUtil.toString(response)
                self.result?(value)
            }
        } catch (let error) {
            let response = ["error": error.localizedDescription]
            let value = try? T3FJsonUtil.toString(response)
            self.result?(value)
        }
    }

    /// 驾车算路
    func driveRoute(arguments: Any?, result: @escaping FlutterResult) {
        self.result = result

        /// arguments示例：
        /// ```
        /// {
        ///     "origin": {
        ///         "longitude": 11.111,
        ///         "latitude": 11.111
        ///    },
        ///    "destination": {
        ///         "longitude": 11.111,
        ///         "latitude": 11.111
        ///    },
        ///    "via": [
        ///         {
        ///             "longitude": 11.111,
        ///             "latitude": 11.111
        ///         },
        ///         {
        ///             "longitude": 11.111,
        ///             "latitude": 11.111
        ///         }
        ///    ],
        ///    "originPoiId": "abcd",
        ///    "destPoiId": "abcd",
        ///    "departureTime": 123456, //时间戳
        /// }
        /// ```
        do {
            let json = try T3FJsonUtil.toJson(arguments)

            if let origin = jsonToCoordinate2D(key: "origin", json: json),
                let destination = jsonToCoordinate2D(key: "destination", json: json) {

                var via: [CLLocationCoordinate2D]?
                if let viaArray = json["via"] as? [[String : Double]] {
                    via = jsonToCoordinate2DArray(json: viaArray)
                }

                let originPoiId = json["originPoiId"] as? String
                let destPoiId = json["destPoiId"] as? String

                //构建request
                let request = QMSDrivingRouteSearchOption()
                request.setFrom(origin)
                request.setTo(destination)
                request.from_poi = originPoiId
                request.to_poi = destPoiId
                request.get_speed = 1
                if var pathPoints = via, !pathPoints.isEmpty {
                    request.setWayPointsWithCoordinates(&pathPoints, count: UInt(pathPoints.count))
                }

                /// 保持引用
                strongSelf = self
                search.searchWithDrivingRouteSearchOption(request)
            }
            else {
                let response = ["error": T3FTNRouteManagerError.dataParseFail.localizedDescription]
                let value = try? T3FJsonUtil.toString(response)
                self.result?(value)
            }
        } catch (let error) {
            let response = ["error": error.localizedDescription]
            let value = try? T3FJsonUtil.toString(response)
            self.result?(value)
        }
    }

    private func jsonToCoordinate2D(key: String, json: [String: Any]) -> CLLocationCoordinate2D? {

        guard let value = json[key] as? [String: Any] else { return nil }
        guard let longitude = value["longitude"] as? Double,
              let latitude = value["latitude"] as? Double
        else { return nil }

        return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    }

    private func jsonToCoordinate2DArray(json: [[String: Any]]) -> [CLLocationCoordinate2D] {

        var array: [CLLocationCoordinate2D] = []

        for ele in json {
            if let longitude = ele["longitude"] as? Double,
               let latitude = ele["latitude"] as? Double {
                array.append(CLLocationCoordinate2D(latitude: latitude, longitude: longitude))
            }
        }

        return array
    }

    deinit {
        print("deinit route manager")
    }
}

extension T3FTNRouteManager: QMSSearchDelegate {

    func search(with walkingRouteSearchOption: QMSWalkingRouteSearchOption, didRecevieResult walkingRouteSearchResult: QMSWalkingRouteSearchResult) {

        defer { strongSelf = nil }

        let routePaths = walkingRouteSearchResult.routes
        let routes = routePlanToJson(routePaths: routePaths)

        let value: [String: Any] = ["routes": routes]
        let retValue = try? T3FJsonUtil.toString(value)
        self.result?(retValue)
    }

    func search(with drivingRouteSearchOption: QMSDrivingRouteSearchOption, didRecevieResult drivingRouteSearchResult: QMSDrivingRouteSearchResult) {

        defer { strongSelf = nil }

        let routePaths = drivingRouteSearchResult.routes
        let routes = routePlanToJson(routePaths: routePaths)

        let value: [String: Any] = ["routes": routes]
        let retValue = try? T3FJsonUtil.toString(value)
        self.result?(retValue)
    }

    private func routePlanToJson(routePaths: [QMSRoutePlan]) -> [[String : Any]] {
        var routes: [[String : Any]] = []
        for routePath in routePaths {
            /// 预计行驶时间，单位：秒。腾讯的单位是分钟
            let duration = routePath.duration * 60
            /// 起点和终点的距离，单位：米
            let distance = routePath.distance
            /// 道路费用，单位：元
            let tolls = routePath.toll
            /// 红绿灯数量，单位：个
            let trafficLightCount = routePath.traffic_light_count
            /// 路线坐标点串
            let polylines = routePath.polyline

            let tag = routePath.tags?.first

            let coordinates = polylines.map { value in
                let coordinate = value.mkCoordinateValue
                return "\(coordinate.longitude),\(coordinate.latitude)"
            }

            let json = [
                "duration" : duration,
                "distance" : distance,
                "tolls"    : tolls,
                "trafficLightCount" : trafficLightCount,
                "polyline" : coordinates.joined(separator: ";"),
                "tag"      : tag ?? ""
            ] as [String : Any]

            routes.append(json)
        }
        return routes
    }

    func search(with searchOption: QMSSearchOption, didFailWithError error: Error) {

        defer { strongSelf = nil }

        let response = ["error": error.localizedDescription]
        let value = try? T3FJsonUtil.toString(response)
        self.result?(value)
    }
}

private enum T3FTNRouteManagerError: Error {
    case dataParseFail
    case noResult
}

extension T3FTNRouteManagerError: CustomStringConvertible {

    var description: String {
        switch self {
        case .dataParseFail:
            return "数据解析异常"
        case .noResult:
            return "未查询到步行路线"
        }
    }
}
